function varargout = TLRelayDlg(action,varargin)

% TL_RELAY_DLG manages the user interface for TargetLink Relay block
%
% SYNTAX dlgInfo = TLRelayDlg('GetDlgInfo');
%   gets dialog info of TargetLink Relay block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLRelayDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLRelayDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLRelayDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLRelayDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLRelayDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLRelayDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.26 $
% $Date: 2011/08/22 10:35:02MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Relay';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames = {
            'Output';
            'Output Values';
            'Switch Points';
            'Logging & Autoscaling';
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output'
                excludedCtrls = {'inheritproperties', 'saturate'};
                [sheetDims, ctrlPos] = tl_calc_ctrls_positions(commonGeom, excludedCtrls);

            case 'Output Values'
                [sheetdims, ctrlPos] = ...
                    FcnCalcOutputValuesCtrlPositions(commonGeom);

            case 'Switch Points'
                [sheetDims, ctrlPos] = ...
                    FcnCalcSwitchPointsCtrlPositions(commonGeom);

            case 'Logging & Autoscaling'
                excludedCtrls = {};
                [sheetDims, ctrlPos] = ...
                    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);

            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims, ctrlPos] = ...
                    TLManageDocCtrls('ctrlpos', commonGeom, sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                % create all controls
                dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
                dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

            case 'Output Values'
                dlgdata = FcnCreateOutputValuesControls(pageNum, dlgfig, dlgdata);

            case 'Switch Points'
                dlgdata = FcnCreateSwitchPointsControls(pageNum, dlgfig, dlgdata);

            case 'Logging & Autoscaling'
                dlgdata = TLManageLoggingCtrls('create', pageNum, dlgfig, dlgdata);

            case 'Documentation'
                dlgdata = TLManageDocCtrls('create', pageNum, dlgfig, dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                [dlgdata, bModified1] = ...
                    TLManageVariableCtrls('manage',pageNum,dlgfig,dlgdata,pageAction,'output');
                [dlgdata, bModified2] = ...
                    TLManageScalingCtrls('manage',pageNum,dlgfig,dlgdata,pageAction,'output');
                bModified = bModified1 || bModified2;

            case 'Output Values'
                [dlgdata, bModified] = ...
                    FcnManageOutputValuesControls(pageNum, dlgfig, dlgdata, pageAction);

            case 'Switch Points'
                [dlgdata,bModified] = ...
                    FcnManageSwitchPointsControls(pageNum, dlgfig, dlgdata, pageAction);

            case 'Logging & Autoscaling'
                [dlgdata, bModified] = ...
                    TLManageLoggingCtrls('manage', pageNum, dlgdata, pageAction, 'logdata');

            case 'Documentation'
                [dlgdata, bModified] = ...
                    TLManageDocCtrls('callback', pageNum, dlgfig, dlgdata, pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified ;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig    = varargin{1};
        dlgdata   = varargin{2};
        pageNum   = varargin{3};

        pageName  = dlgdata.pageNames{pageNum};

        switch pageName
            case 'Output'
                % update all controls
                dlgdata = TLManageVariableCtrls('update',pageNum,dlgdata,'output');
                dlgdata = TLManageScalingCtrls('update',pageNum,dlgdata,'output', []);

                % set controls
                TLManageVariableCtrls('setCtrls',pageNum,dlgfig,dlgdata);
                TLManageScalingCtrls('setCtrls',pageNum,dlgfig,dlgdata);

            case 'Output Values'
                dlgdata = FcnUpdateOutputValuesControls(dlgdata, dlgfig, pageNum);

            case 'Switch Points'
                dlgdata = FcnUpdateSwitchPointsControls(dlgdata, dlgfig, pageNum);

            case 'Logging & Autoscaling'
                dlgdata =  FcnUpdataLoggingControls(pageNum, dlgfig, dlgdata);

            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action "' action '"']);

end

%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        switch dlgdata.pageNames{dlgdata.CurrentPageNum}
            case 'Output Values'
                % 'onoutput' and 'offoutput' are on one page without selection popup
                tl_create_links_to_model('ShowDeclaration',dlgdata.model, 'onoutput');
            case 'Switch Points'
                blockVar{1} = 'onswitch';
                blockVar{2} = 'offswitch';
                idx = get(dlgdata.pageData{3}.children.selectPopup,'Value');
                tl_create_links_to_model('ShowDeclaration',dlgdata.model, blockVar{idx});
            otherwise
                blockVar = 'output';
                tl_create_links_to_model('ShowComputation',dlgdata.model, blockVar);
        end

    otherwise
        error('Invalid callback');

end % switch(action)


% HINT:
% The functions that deal with the Output Values page implement a
% workaround for a design limitation in the general dialog functions
% TLManageVariableCtrls etc. The Relay block is the only block that has
% more than one Production Code Options groupbox on one page, but the
% general functions are designed to handle one of those only.
% Therfore the general functions are called twice each time, with the calling 
% code moving around and renaming parts of the dlgdata structure as appropriate.

%-----------------------------------------------------------------------------------------
% FcnCalcOutputValuesCtrlPositions calculates positions for all controls on output values page
%
% INPUT ARGUMENTS
%   commonGeom      common geometry information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcOutputValuesCtrlPositions(commonGeom)

% calculate positions of offOutput groupbox
excludedCtrls = {'allscaling', 'scaling', 'type', ...
    'width', 'element', 'inheritproperties', 'scalarExp'};
[sheetDims, stdCtrlPos, col, colDelta, rowDelta, colWidth] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

useDDValueCheckboxSize = ds_get_uicontrol_sizes(commonGeom, ...
    {'Use value of Data Dictionary variable', 'checkbox'});

% copy coordinates
fieldNameList = fieldnames(stdCtrlPos);
fieldNameList(strcmp(fieldNameList,'tlcgoptGroupbox')) = [];
fieldNameList(strcmp(fieldNameList,'addoptGroupbox'))   = [];
fieldNameList(strcmp(fieldNameList,'addoptGroupbox'))     = [];
fieldNameList = reshape(fieldNameList,1,length(fieldNameList));

% ctrlPos is normally a flat structure containing coordinates for all
% controls on a page. Here, the production code controls for the onOutput
% and offOutput variables are contained in substructures below ctrlPos
for fieldName = fieldNameList,
    fieldStr = char(fieldName);
    coords = stdCtrlPos.(fieldStr);
    ctrlPos.offOutput.(fieldStr) = coords;
    ctrlPos.onOutput.(fieldStr) = coords;
end

% reposition groupboxes on top of each other
ctrlPos.tlcgoptOffGroupbox   = stdCtrlPos.tlcgoptGroupbox;
ctrlPos.tlcgoptOnGroupbox    = stdCtrlPos.tlcgoptGroupbox;
ctrlPos.addoptGroupbox       = stdCtrlPos.addoptGroupbox;
ctrlPos.tlcgoptOnGroupbox(2) = ctrlPos.tlcgoptOnGroupbox(2) ...
    + ctrlPos.tlcgoptOffGroupbox(4) ...
    + commonGeom.textHeight;
ctrlPos.addoptGroupbox(2)    = ctrlPos.addoptGroupbox(2) ...
    + ctrlPos.tlcgoptOnGroupbox(4) ...
    + commonGeom.textHeight;

% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

% ddv checkboxes
cx = col(2);
ctrlPos.onOutputDdvCheckbox = [cx, cy, useDDValueCheckboxSize];

cx = col(6);
ctrlPos.offOutputDdvCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% onOutput label
cx = col(1);
ctrlPos.onOutputValueLabel = [cx,cy,ctrlPos.onOutput.descLabel(3:4)];

% onOutput edit
cx = col(2);
ctrlPos.onOutputValueEdit = [cx,cy,ctrlPos.onOutput.varEdit(3:4)];

% offOutput label
cx = col(6) - ctrlPos.onOutput.descLabel(3) - colDelta/3;
ctrlPos.offOutputValueLabel = [cx, cy, ctrlPos.onOutput.descLabel(3:4)];

% offOutput edit
cx = col(6);
ctrlPos.offOutputValueEdit = [cx,cy,ctrlPos.onOutput.varEdit(3:4)];

sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight ...
    + rowDelta;


%-----------------------------------------------------------------------------------------
% FcnCreateOutputValuesControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputValuesControls(pageNum, dlgfig, dlgdata)

% create standard controls
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
dlgdata.pageData{pageNum}.ctrlPos = ctrlPos.offOutput;
dlgdata.pageData{pageNum}.ctrlPos.tlcgoptGroupbox = ctrlPos.tlcgoptOffGroupbox;
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata, 'offOutput');

% save control handles for offOutput controls
tempOffOutputChildren = dlgdata.pageData{pageNum}.children;
% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'Variable for output value ''off''');
standardControlsNames = transpose(fieldnames(tempOffOutputChildren));
dlgdata.pageData{pageNum}.children = [];

% create standard controls for onOutput
dlgdata.pageData{pageNum}.ctrlPos = ctrlPos.onOutput;
dlgdata.pageData{pageNum}.ctrlPos.tlcgoptGroupbox = ctrlPos.tlcgoptOnGroupbox;
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata, 'onOutput');

% save control handles for onOutput controls
tempOnOutputChildren = dlgdata.pageData{pageNum}.children;
% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'Variable for output value ''on''');
Children = [];

% create unique names for all production code option controls. We can't use
% the substructures trick (as in ctrlPos) here because the general dialog
% functions expect a flat structure with all controls on the page
for ctrlName = standardControlsNames
    Children.(['onOutput' char(ctrlName)])  = tempOnOutputChildren.(char(ctrlName));
    Children.(['offOutput' char(ctrlName)]) = tempOffOutputChildren.(char(ctrlName));
end

pageName = dlgdata.pageNames{pageNum};

% create extra controls
% create the value frame
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Output values'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% onOutput value label
Children.onOutputValueLabel = uicontrol( ...
    'Parent',            Children.addoptGroupbox, ...
    'Style',             'text', ...
    'String',            'When ''on'':', ...
    'Position',          ctrlPos.onOutputValueLabel);

% onOutput value edit field
Children.onOutputValueEdit = uicontrol( ...
    'Parent',            Children.addoptGroupbox, ...
    'BackGroundColor',   'w', ...
    'Style',             'edit', ...
    'Position',          ctrlPos.onOutputValueEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''onOutputValueEdit'')',pageName));

% offOutput value label
Children.offOutputValueLabel = uicontrol( ...
    'Parent',            Children.addoptGroupbox, ...
    'Style',             'text', ...
    'String',            'When ''off'':', ...
    'Position',          ctrlPos.offOutputValueLabel);

% offOutput value edit field
Children.offOutputValueEdit = uicontrol( ...
    'Parent',            Children.addoptGroupbox, ...
    'BackGroundColor',   'w', ...
    'Style',             'edit', ...
    'Position',          ctrlPos.offOutputValueEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''offOutputValueEdit'')',pageName));

Children.onOutputDdvCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.onOutputDdvCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''onOutputDdvCheckbox'')',pageName));

Children.offOutputDdvCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.offOutputDdvCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''offOutputDdvCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;

% base names of all production code options controls (e.g. 'descEdit'). The
% actual control names are prefixed with either 'onOutput' or 'offOutput'
% (e.g. onOutputdescEdit)
dlgdata.pageData{pageNum}.standardControlsNames = standardControlsNames;
dlgdata.pageData{pageNum}.ctrlPos = [];


%-----------------------------------------------------------------------------------------
% FcnManageOutputValuesControls manage control actions of output values page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputValuesControls(pageNum,dlgfig,dlgdata,pageAction)

bModified = false;
Children = dlgdata.pageData{pageNum}.children;

switch pageAction
    case {'offOutputValueEdit', 'onOutputValueEdit'}
        numChars = numel(pageAction) - numel('ValueEdit');
        propName = lower(pageAction(1:numChars));
        value = tl_deblank(get(Children.(pageAction), 'String'), 2);
        if ~isempty(value)
            if strcmp(value, 'ddv')
                if isempty(dlgdata.data.(propName).variable)
                    beep;
                else
                    dlgdata.data.(propName).value = ['ddv(''', dlgdata.data.(propName).variable, ''')'];
                    dlgdata.data.(propName).useddvariablevalue = true;
                end
            else
                dlgdata.data.(propName).value = value;
            end
        else
            beep;
        end
        bModified = true;

    case {'onOutputDdvCheckbox', 'offOutputDdvCheckbox'}
        numChars = numel(pageAction) - numel('DdvCheckbox');
        propName = lower(pageAction(1:numChars));
        if get(Children.(pageAction), 'Value')
            dlgdata.data.(propName).value = ['ddv(''', dlgdata.data.(propName).variable, ''')'];
            dlgdata.data.(propName).useddvariablevalue = true;
        else
            dlgdata.data.(propName).useddvariablevalue = false;
        end
        bModified = true;

    otherwise
        % one of the standard controls has been operated
        offOutputChildren = [];
        onOutputChildren = [];
        for fieldName = dlgdata.pageData{pageNum}.standardControlsNames
            offOutputChildren.(char(fieldName)) = Children.(['offOutput' char(fieldName)]);
            onOutputChildren.(char(fieldName)) = Children.(['onOutput' char(fieldName)]);
        end

        % standard control names either begin with 'onOutput' or 'offOutput'.
        % The prefix has to be stripped before the call to TLManageVariableCtrls.
        if strcmp(pageAction(1:8), 'onOutput')
            % manage onoutput callbacks
            dlgdata.pageData{pageNum}.children = onOutputChildren;
            [dlgdata, bModified] = TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction(9:end), 'onoutput');
            if bModified && any(strcmp(pageAction(9:end), {'classEdit', 'classSelectButton'}))
                % make sure both output value variables have the same variable class
                dlgdata.data.offoutput.class = dlgdata.data.onoutput.class;
            end
        elseif strcmp(pageAction(1:9), 'offOutput')
            % manage offoutput callbacks
            dlgdata.pageData{pageNum}.children = offOutputChildren;
            [dlgdata, bModified] = TLManageVariableCtrls('manage', pageNum, dlgfig, dlgdata, pageAction(10:end), 'offoutput');
            if bModified && any(strcmp(pageAction(10:end), {'classEdit', 'classSelectButton'}))
                % make sure both output value variables have the same variable class
                dlgdata.data.onoutput.class = dlgdata.data.offoutput.class;
            end
        end
        dlgdata.pageData{pageNum}.children = Children;
end


%--------------------------------------------------------------------------
% FcnUpdateOutputValuesControls updates the controls of the output values tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputValuesControls(dlgdata, dlgfig, pageNum)

% prepare Children structure for first TLManageVariableCtrls call:
% include offOutput controls only, strip 'offOutput' prefix.
Children = dlgdata.pageData{pageNum}.children;
offOutputChildren = [];
onOutputChildren = [];
for fieldName = dlgdata.pageData{pageNum}.standardControlsNames
    offOutputChildren.(char(fieldName)) = Children.(['offOutput' char(fieldName)]);
    onOutputChildren.(char(fieldName))  = Children.(['onOutput' char(fieldName)]);
end

% update standard controls for offOutput
dlgdata.pageData{pageNum}.children = offOutputChildren;
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'offoutput');
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);

% now prepare Children structure for the second TLManageVariableCtrls
% call: onOutput controls only
% update standard controls for onOutput
dlgdata.pageData{pageNum}.children = onOutputChildren;
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'onoutput');
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);

dlgdata.pageData{pageNum}.children = Children;

% default control status for controls of output values groupbox
offOutputValueEditCtrlStatus = struct('enable', 'on', 'string', dlgdata.data.offoutput.value);
onOutputValueEditCtrlStatus = struct('enable', 'on', 'string', dlgdata.data.onoutput.value);
if dlgdata.data.offoutput.useddvariablevalue
    offOutputValueEditCtrlStatus.enable = 'inactive';
end
if dlgdata.data.onoutput.useddvariablevalue
    onOutputValueEditCtrlStatus.enable = 'inactive';
end

% status of ddv checkbox
offOutputDdvCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.offoutput.variable));
offOutputDdvCheckboxCtrlStatus.value = dlgdata.data.offoutput.useddvariablevalue;
onOutputDdvCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.onoutput.variable));
onOutputDdvCheckboxCtrlStatus.value = dlgdata.data.onoutput.useddvariablevalue;

% set status of extra controls
ctrlsList = { ...
    'offOutputValueEdit', ...
    'onOutputValueEdit', ...
    'offOutputDdvCheckbox', ...
    'onOutputDdvCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);


%-----------------------------------------------------------------------------------------
% FcnCalcOutputValuesCtrlPositions calculates positions for switch point controls 
%
% INPUT ARGUMENTS
%   commonGeom      common geometry information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcSwitchPointsCtrlPositions(commonGeom)

excludedCtrls = {'calcranges', 'inheritproperties', 'saturate'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

strings_and_styles = {...
    'Select:',                 'text';
    'Switch off',              'text';
    'Scalar',                  'checkbox';
    'Scale Switch Point',      'pushbutton';
    'Use value of Data Dictionary variable', 'checkbox'};

[selectLabelSize, ...
    switchPointLabelSize, ...
    scalarCheckboxSize, ...
    autoscaleButtonSize, ...
    useDDValueCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% calculate extra space needed for select popup
dy = commonGeom.editHeight + rowDelta;

% enlarge tlcgGroupbox and move addoptGroupbox
ctrlPos.tlcgoptGroupbox(4) = ctrlPos.tlcgoptGroupbox(4) + dy;
ctrlPos.addoptGroupbox(2)  = ctrlPos.addoptGroupbox(2)  + dy;
ctrlPos.addoptGroupbox(4)  = ctrlPos.addoptGroupbox(4)  + dy;

% supplement tlcgGroupbox
cy = ctrlPos.descLabel(2) + commonGeom.editHeight + rowDelta;

% select label
cx = col(1);
ctrlPos.selectLabel = [cx cy selectLabelSize];

% select popup
cx = col(2);
ctrlPos.selectPopup = [cx cy ctrlPos.lsbEdit(3:4)];

% switch point autoscale button
cx = cx + ctrlPos.selectPopup(3) + colDelta / 3;
ctrlPos.scaleSwitchPointButton = [cx,cy, autoscaleButtonSize];

% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + 2 * commonGeom.checkboxHeight ...
    + 2 * rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

%---------------------------------------
% 3rd row
cy = commonGeom.frameBottomEdgeBuffer;

% ddv checkbox associated with onswitch value
cx = col(2);
ctrlPos.onSwitchDdvCheckbox = [cx, cy, useDDValueCheckboxSize];

% ddv checkbox associated with offswitch value
cx = col(6);
ctrlPos.offSwitchDdvCheckbox = [cx, cy, useDDValueCheckboxSize];

%---------------------------------------
% 2nd row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% scalar checkbox for switch on
cx = col(2);
ctrlPos.onSwitchScalarCheckbox = [cx cy scalarCheckboxSize];

% scalar checkbox for switch off
cx = col(6);
ctrlPos.offSwitchScalarCheckbox = [cx cy scalarCheckboxSize];

% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% switch point on label
cx = col(1);
ctrlPos.onSwitchLabel = [cx cy switchPointLabelSize];

% switch point on edit field
cx = col(2);
ctrlPos.onSwitchEdit = [cx cy ctrlPos.varEdit(3:4)];

% switch point off label
cx = col(6) - switchPointLabelSize(1) - colDelta / 3;
ctrlPos.offSwitchLabel = [cx cy switchPointLabelSize];

% switch point off edit field
cx = col(6);
ctrlPos.offSwitchEdit = [cx cy ctrlPos.varEdit(3:4)];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight ...
    + dy;


%-----------------------------------------------------------------------------------------
% FcnCreateSwitchPointsControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateSwitchPointsControls(pageNum, dlgfig, dlgdata)

% create standard controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};

% variable select controls
Children.selectLabel = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'String',             'Select:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.selectLabel);

Children.selectPopup = uicontrol( ...
    'Parent',             Children.tlcgoptGroupbox, ...
    'Style',              'Popupmenu', ...
    'String',             {'Switch on'}, ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.selectPopup, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''selectPopup'')',pageName));

% create the addoptGroupbox which will contain switch point controls
Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Switch points'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% variable value controls
Children.onSwitchLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Switch on:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.onSwitchLabel);

Children.onSwitchEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.onSwitchEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''onSwitchEdit'')',pageName));

Children.offSwitchLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'String',             'Switch off:', ...
    'Style',              'text', ...
    'Position',           ctrlPos.offSwitchLabel);

Children.offSwitchEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'BackgroundColor',    'w', ...
    'Position',           ctrlPos.offSwitchEdit, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''offSwitchEdit'')',pageName));

Children.onSwitchScalarCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Scalar', ...
    'Position',           ctrlPos.onSwitchScalarCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''onSwitchScalarCheckbox'')',pageName));

Children.offSwitchScalarCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Scalar', ...
    'Position',           ctrlPos.offSwitchScalarCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''offSwitchScalarCheckbox'')',pageName));

Children.scaleSwitchPointButton = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             'Scale Switch Point', ...
    'Position',           ctrlPos.scaleSwitchPointButton, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''scaleSwitchPointButton'')',pageName));

Children.onSwitchDdvCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.onSwitchDdvCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''onSwitchDdvCheckbox'')',pageName));

Children.offSwitchDdvCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Use value of Data Dictionary variable', ...
    'Position',           ctrlPos.offSwitchDdvCheckbox, ...
    'Callback',           sprintf('tldlg(''%s'',gcbf,''offSwitchDdvCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputValuesControls manage control actions of switch points
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSwitchPointsControls(pageNum, dlgfig, dlgdata, pageAction)

Children   = dlgdata.pageData{pageNum}.children;
fieldIdx   = get(Children.selectPopup, 'Value');

switch fieldIdx
    case 1
        field = 'onswitch';
    case 2
        field = 'offswitch';
end

switch pageAction

    case {'onSwitchEdit', 'offSwitchEdit'}
        numChars = numel(pageAction) - numel('Edit');
        propName = lower(pageAction(1:numChars));
        value = deblank(get(Children.(pageAction), 'String'));
        if ~isempty(value)
            if strcmp(value, 'ddv')
                if isempty(dlgdata.data.(propName).variable)
                    beep;
                else
                    dlgdata.data.(propName).value = ['ddv(''', dlgdata.data.(propName).variable, ''')'];
                    dlgdata.data.(propName).useddvariablevalue = true;
                end
            else
                dlgdata.data.(propName).value = value;
            end
        else
            beep;
        end
        bModified = true;

    case {'onSwitchScalarCheckbox', 'offSwitchScalarCheckbox'}
        numChars = numel(pageAction) - numel('ScalarCheckbox');
        propName = lower(pageAction(1:numChars));
        dlgdata.data.(propName).scalar = get(Children.(pageAction), 'Value');
        bModified = true;
        
    case {'onSwitchDdvCheckbox', 'offSwitchDdvCheckbox'}
        numChars = numel(pageAction) - numel('DdvCheckbox');
        propName = lower(pageAction(1:numChars));
        if get(Children.(pageAction), 'Value')         
            dlgdata.data.(propName).value = ['ddv(''', dlgdata.data.(propName).variable, ''')'];
            dlgdata.data.(propName).useddvariablevalue = true;
        else
            dlgdata.data.(propName).useddvariablevalue = false;
        end
        bModified = true;

    case 'selectPopup'
        bModified = true;

    case 'scaleSwitchPointButton'
        options.selectDatatypeSign = 'yes';
        options.minimizeWordWidth  = 'yes';
        ds_error_none;
        [dlgdata.data, bModified, msgstruct] = tl_scale_parameters( ...
            dlgdata.model, dlgdata.data, options, field);
        ds_error_register(msgstruct);
        ds_msgdlg('Update', ...
            'Title', ['Scaling of ' get_tlsubsystempath(dlgdata.model) '->' field], ...
            'ShowErrors', 'yes', ...
            'ShowNotes', 'yes', ...
            'ShowWarnings', 'yes');

    otherwise
        [dlgdata, bModified1] = ...
            TLManageVariableCtrls('manage',pageNum,dlgfig,dlgdata,pageAction,field);

        if bModified1 && any(strcmp(pageAction, {'classEdit', 'classSelectButton'}))
            % make sure both switch point variables have the same variable class
            dlgdata.data.onswitch.class = dlgdata.data.(field).class;
            dlgdata.data.offswitch.class = dlgdata.data.(field).class;
        end
        [dlgdata,bModified2] = ...
            TLManageScalingCtrls('manage',pageNum,dlgfig,dlgdata,pageAction,field);
        bModified = bModified1 || bModified2;

end


%--------------------------------------------------------------------------
% FcnUpdateSwitchPointsControls updates the switch point controls
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateSwitchPointsControls(dlgdata, dlgfig, pageNum)

% default control status
onSwitchEditCtrlStatus            = struct('enable', 'on');
offSwitchEditCtrlStatus           = struct('enable', 'on');
onSwitchScalarCheckboxCtrlStatus  = struct('enable', 'on');
offSwitchScalarCheckboxCtrlStatus = struct('enable', 'on');
selectPopupCtrlStatus             = struct( ...
    'enable', 'on', ...
    'value', 1, ...
    'string', {{'Switch on'; 'Switch off'}});
scaleSwitchPointButtonCtrlStatus  = struct('enable', 'on');

% determine selected field
Children = dlgdata.pageData{pageNum}.children;
fieldIdx = get(Children.selectPopup, 'Value');
switch fieldIdx
    case 1
        field = 'onswitch';
        otherField = 'offswitch';
    case 2
        field = 'offswitch';
        otherField = 'onswitch';
end
selectPopupCtrlStatus.value = fieldIdx;

if strcmp(tl_deblank(dlgdata.data.onswitch.class, 2), 'default')
    dlgdata.data.onswitch.scalar = 0;
    onSwitchScalarCheckboxCtrlStatus.enable = 'off';
end
if strcmp(tl_deblank(dlgdata.data.offswitch.class, 2), 'default')
    dlgdata.data.offswitch.scalar = 0;
    offSwitchScalarCheckboxCtrlStatus.enable = 'off';
end

% if scalar is selected, scalar Expansion Flag is selected as well (and is
% later disabled)
if dlgdata.data.onswitch.scalar
    dlgdata.extdata.onswitch.scalarExp = 1;
end
if dlgdata.data.offswitch.scalar
    dlgdata.extdata.offswitch.scalarExp = 1;
end

% update standard controls
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, otherField);
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, field);

[dlgdata, switchpoint, constraint, errorDescription] = FcnCheckLimit( ...
    dlgdata, otherField, false);

[dlgdata, switchpoint, constraint, errorDescription] = FcnCheckLimit( ...
    dlgdata, field, true, errorDescription);

% evaluate error description and apply to the corresponding edit controls
bCurrentParameterInvalid = errorDescription.(field);

onSwitchScalarCheckboxCtrlStatus.value = dlgdata.data.onswitch.scalar;
offSwitchScalarCheckboxCtrlStatus.value = dlgdata.data.offswitch.scalar;

onSwitchEditCtrlStatus.string = dlgdata.data.onswitch.value;
if dlgdata.data.onswitch.useddvariablevalue
    onSwitchEditCtrlStatus.enable = 'inactive';
end
onSwitchEditCtrlStatus.iserror = errorDescription.onswitch;

offSwitchEditCtrlStatus.string = dlgdata.data.offswitch.value;
if dlgdata.data.offswitch.useddvariablevalue
    offSwitchEditCtrlStatus.enable = 'inactive';
end
offSwitchEditCtrlStatus.iserror = errorDescription.offswitch;

% status of ddv checkboxes
onSwitchDdvCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.onswitch.variable));
onSwitchDdvCheckboxCtrlStatus.value = dlgdata.data.onswitch.useddvariablevalue;
offSwitchDdvCheckboxCtrlStatus.enable = flag2str(~isempty(dlgdata.data.offswitch.variable));
offSwitchDdvCheckboxCtrlStatus.value = dlgdata.data.offswitch.useddvariablevalue;

% for parameters there are no simulated ranges.
% Instead, write min/max of parameter value
simulatedLabelCtrlStatus = tl_get_control_userdata(Children.simulatedLabel);
upperSimulatedValueCtrlStatus = tl_get_control_userdata(Children.upperSimulatedValue);
lowerSimulatedValueCtrlStatus = tl_get_control_userdata(Children.lowerSimulatedValue);

if dlgdata.extdata.(field).scalarExp
    simulatedLabelCtrlStatus.string = ['of ' field];
else
    simulatedLabelCtrlStatus.string = 'of element';
end

if ~strcmp(tl_deblank(dlgdata.data.(field).class, 2), 'default')
    % fill row with simulated values
    if ~isempty(constraint)
        lowerSimulatedValueCtrlStatus.string = sprintf('%0.6g', min(constraint));
        upperSimulatedValueCtrlStatus.string = sprintf('%0.6g', max(constraint));
    else
        lowerSimulatedValueCtrlStatus.string = 'n.a.';
        upperSimulatedValueCtrlStatus.string = 'n.a.';
    end
end

scalarExpCheckboxCtrlStatus = tl_get_control_userdata(Children.scalarExpCheckbox);
if dlgdata.data.(field).scalar
    scalarExpCheckboxCtrlStatus.enable = 'off';
end

typeString = ['/Pool/Typedefs/' dlgdata.data.(field).type];
buttonEnable = dlgdata.bIsFullVs & ~bCurrentParameterInvalid & ...
    all(isfinite(constraint)) & ...
    ds_isa(typeString, 'integertype') & ...
    ~ds_isa(typeString, 'constrainedtype');

scaleSwitchPointButtonCtrlStatus.enable = flag2str(buttonEnable);

% write back to UserData
extraCtrlsList = {
    'onSwitchEdit', ...
    'onSwitchScalarCheckbox', ...
    'onSwitchDdvCheckbox', ...
    'offSwitchEdit', ...
    'offSwitchScalarCheckbox', ...
    'offSwitchDdvCheckbox', ...
    'scaleSwitchPointButton', ...
    'selectPopup'};
standardCtrlsList = {
    'scalarExpCheckbox', ...
    'simulatedLabel', ...
    'simulatedLabel', ...
    'upperSimulatedValue', ...
    'lowerSimulatedValue'};
ctrlsList = [extraCtrlsList standardCtrlsList];
for ctrlsNo=1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set control status of standard controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);

% set status of rate controls
TLSetCtrlsStatus(dlgfig, Children, extraCtrlsList)


%-----------------------------------------------------------------------------------------
% FcnUpdataLoggingControls updates output page
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata =  FcnUpdataLoggingControls(pageNum,dlgfig,dlgdata)

dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'logdata','output');

Children = dlgdata.pageData{pageNum}.children;

% overwrite control status of offset
keepParamOffsetCheckboxCtrlStatus     = struct('enable', 'inactive', 'value', 1);   %#ok
ctrlsList = {'keepParamOffsetCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    if strcmp(UserData.ctrlStatus.enable, 'on')
        UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
        set(ctrl, 'UserData', UserData);
    end
end

TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);


%--------------------------------------------------------------------------
% FcnCheckLimit checks the constraints on limits
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   field       current field
%   bVisible    flag =1, if field has scaling controls, =0 otherwise
%   errorDescription    structure of error flags
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   limit       limit
%   constraint  constraint
%   errorDescription    structure of error flags
%--------------------------------------------------------------------------
function [dlgdata, limit, constraint, errorDescription] = ...
    FcnCheckLimit(dlgdata, field, bVisible, errorDescription)

if nargin == 3
    errorDescription = struct();
end

[limit, constraint, bCompliant] = ...
    tl_get_param_constraints(dlgdata.data.(field), dlgdata.extdata.(field));

pageNum = 3;
if bVisible
    dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, field, constraint);
end

errorDescription.(field) = ~bCompliant;
